#include "../pix5core.h"
#include "LinuxFS.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>


class CEX LinuxFile:public File
{
	int _fd;
	bool _write;

public:
	
	virtual const char* __getName(){return "LinuxFile";}

	LinuxFile(int fd,bool write)
	{
		_fd = fd;
		_write = write;
	}

	~LinuxFile()
	{
		close();
	}

	void close()
	{
		if(_fd!=-1)
		{
			::close(_fd);
			_fd = -1;
		}
	}

	long long getSize()
	{
		if(_fd==-1)
			throw Error("File is closed");

		struct stat s;
		if(fstat(_fd,&s))
			throw Error(strerror(errno));

		return s.st_size;
	}

	void setPos(long long pos)
	{
		if(_fd==-1)
			throw Error("File is closed");

		if(lseek64(_fd,pos,SEEK_SET)==-1)
			throw Error(strerror(errno));
	}

	long long getPos()
	{
		if(_fd==-1)
			throw Error("File is closed");

		long long pos = lseek64(_fd,0,SEEK_CUR);
		if(pos==-1)
			throw Error(strerror(errno));

		return pos;
	}

	DateTime getModTime()
	{
		if(_fd==-1)
			throw Error("File is closed");

		struct stat s;
		if(fstat(_fd,&s))
			throw Error(strerror(errno));

		return DateTime(s.st_mtime);
		
	}


	void read(void* ptr,int size)
	{
		if(_fd==-1)
			throw Error("File is closed");

		ssize_t szt = ::read(_fd,ptr,size);
		if(szt==-1)
			throw Error(strerror(errno));
		if(szt<size)
			throw Error("Reading past end of file");
	}

	void write(void* ptr,int size)
	{
		if(_fd==-1)
			throw Error("File is closed");

		if(!_write)
			throw Error("File is opened read-only");
	
		ssize_t szt = ::write(_fd,ptr,size);
		if(szt==-1)
			throw Error(strerror(errno));
		if(szt<size)
			throw Error("Write error");
	}
	

};



LinuxFS::LinuxFS()
{
}

LinuxFS::~LinuxFS()
{
}


File* LinuxFS::openFile(const String& filename,bool write,bool create)
{
	int flags = 0;

	if(write)
	{
		flags = O_RDWR;

		if(create)
			flags |= O_CREAT | O_TRUNC;
	}
	else
		flags = O_RDONLY;
	
	int fd = open(filename,flags,S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);

	if(fd==-1)
		throw Error(strerror(errno));
	
	return new LinuxFile(fd,write);

}


